package models

import (
	"gin-AssetManagement/utils"
	"gorm.io/gorm"
)

type Menus struct {
	gorm.Model
	Name        string  `form:"name" json:"name"`
	URL         string  `form:"url" json:"url"`
	RequestType string  `form:"request_type" json:"request_type"`
	Icon        string  `form:"icon" json:"icon"`
	ParentID    uint    `form:"parent_id" json:"parent_id"`
	ParentName  string  `form:"parent_name" json:"parent_name"`
	Level       uint8   `form:"level" json:"level"`
	Type        uint8   `form:"type" json:"type"`
	Sort        uint    `form:"order" json:"sort"`
	Roles       []Roles `gorm:"many2many:roles_menus;"`
}
type MenusJson struct {
	ID          uint         `json:"ID"`
	Name        string       `json:"name"`
	URL         string       `json:"URL"`
	RequestType string       `form:"request_type" json:"request_type"`
	Icon        string       `json:"icons"`
	ParentID    uint         `json:"parentID"`
	ParentName  string       `json:"parentName"`
	Level       uint8        `json:"level"`
	Type        uint8        `json:"type"`
	Sort        uint         `json:"sort"`
	Children    []*MenusJson `json:"children"` // 添加子菜单字段
}

func init() {
	err := DB.AutoMigrate(&Menus{})
	if err != nil {
		return
	}
}

// CreateMenus 添加菜单
func (m *Menus) CreateMenus() error {
	result := DB.Create(m)
	if result.Error != nil {
		return result.Error
	}
	return nil
}

// GetMenusList 获取菜单
func GetMenusList() (m []Menus, count int64, err error) {
	err = DB.Order("sort asc").Find(&m).Count(&count).Error
	if err != nil {
		return
	}
	return
}

// GetMenusByUserId 根据用户ID查询有权限的菜单
func GetMenusByUserId(userID any) (m []Menus, err error) {
	var roelsID []uint
	var user Users
	var roles Roles
	err = DB.Preload("Roles").Take(&user, userID).Error
	if err != nil {
		return nil, err
	}
	for _, v := range user.Roles {
		roelsID = append(roelsID, v.ID)
	}
	// 判断是否是管理员权限
	if utils.IsAdmins(roelsID) {
		err = DB.Order("sort asc").Where("type = ?", 0).Find(&m).Error
		if err != nil {
			return nil, err
		}
		return
	}
	for _, v := range roelsID {
		err1 := DB.Preload("Menus", func(db *gorm.DB) *gorm.DB {
			return db.Order("sort ASC").Where("type = ?", 0)
		}).Find(&roles, v).Error
		if err1 != nil {
			return nil, err1
		}
		m = append(m, roles.Menus...)
	}
	return
}

// LoadMenu 加载树形菜单
func LoadMenu(menu *MenusJson, menuData []Menus) []*MenusJson {
	processedIDs := make(map[uint]bool) // 创建一个映射来存储已处理的菜单ID
	for _, m := range menuData {
		if m.ParentID == menu.ID && !processedIDs[m.ID] { // 检查菜单ID是否已处理
			processedIDs[m.ID] = true // 标记菜单ID为已处理

			childMenu := &MenusJson{
				ID:          m.ID,
				Name:        m.Name,
				URL:         m.URL,
				RequestType: m.RequestType,
				Icon:        m.Icon,
				ParentID:    m.ParentID,
				ParentName:  m.ParentName,
				Level:       m.Level,
				Type:        m.Type,
				Sort:        m.Sort,
				Children:    []*MenusJson{}, // 初始化子菜单切片
			}
			LoadMenu(childMenu, menuData)
			menu.Children = append(menu.Children, childMenu)
		}
	}
	return menu.Children
}

// DelMneus 根据ID删除菜单
func (m *Menus) DelMneus() error {
	err := DB.Transaction(func(tx *gorm.DB) error {
		// 先删除菜单和角色关联
		err := tx.Exec(`
		  WITH RECURSIVE cte_recursive AS (
		      SELECT id, parent_id
		      FROM menus
		      WHERE id = ?
		      UNION ALL
		      SELECT t.id, t.parent_id
		      FROM menus t
		      INNER JOIN cte_recursive r ON t.parent_id = r.id
		  )
		  DELETE FROM roles_menus
		  WHERE menus_id IN (
		      SELECT id
		      FROM cte_recursive
		  )
		`, m.ID).Error
		if err != nil {
			return err
		}
		// 在删除菜单
		err = tx.Exec(`
		  WITH RECURSIVE cte_recursive AS (
		      SELECT id, parent_id
		      FROM menus
		      WHERE id = ?
		      UNION ALL
		      SELECT t.id, t.parent_id
		      FROM menus t
		      INNER JOIN cte_recursive r ON t.parent_id = r.id
		  )
		  DELETE FROM menus
          WHERE id IN (
	       SELECT id
	       FROM cte_recursive
	      )
		`, m.ID).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	return nil
}

// UpdateMenus 根据ID更新菜单
func (m *Menus) UpdateMenus(fields, value string) error {
	return DB.Model(m).Update(fields, value).Error
}

// QueryMenusByIds 根据菜单id查询菜单集合
func QueryMenusByIds(ids []int) (menus []Menus, err error) {
	if len(ids) != 0 {
		if err = DB.Find(&menus, ids).Error; err != nil {
			return
		}
	}
	return
}
